#ifndef _KLAS_SOUND_ENGINE_HPP_
#define _KLAS_SOUND_ENGINE_HPP_

#include "../include/Data.hpp"
#include "../include/Vector2.hpp"
#include "../include/Libs.hpp"
#include <vector>
#include <iostream>
using namespace std;

namespace klas
{
  class Music : public DataObject
  {
    public:
      Music(string file);
      virtual ~Music();
      virtual bool isValid() const;
      virtual iReal getObjectType() const;
      virtual bool kill();
      Mix_Music* getMusic() const;

    private:
      Mix_Music* m_music;
  };

  class SoundEffect : public DataObject
  {
    public:
      SoundEffect(string file);
      virtual ~SoundEffect();
      virtual bool isValid() const;
      virtual iReal getObjectType() const;
      virtual bool kill();
      Mix_Chunk* getEffect() const;

    private:
      Mix_Chunk* m_effect;
  };

  //! The sound engine supports the playing and loading of music files and sound effects.
  class SoundEngine
  {
    public:

      //! Ctor.
      /*! \param targetNumOfTracks An estimate of the number of tracks that will be added to the sound engine.  Used for optimization.
          \param frequency Output sampling frequency in samples per second (Hz).
          \param channels 1 for mono, 2 for stero.
          \param chunkSize Bytes used per output sample.
          \param format The output sample format. */
      SoundEngine(iReal targetNumOfTracks = 10, iReal frequency = 22050, iReal channels = 2, iReal chunkSize = 4096, Uint16 format = MIX_DEFAULT_FORMAT);

      //! Dtor.
      ~SoundEngine();

      //! Plays a music effect.
      /*! \param effect The effect to play.
          \param loops The number of times to loop the effect.
          \return True if success, false on error. */
      bool playEffect(DataObject* effect, iReal loops = 0);

      //! Plays a music tract.
      /*! \param music The music to play.
          \param loops The number of times to loop the music.
          \param startSeconds At which second to start playing.
          \param fadeTimeInMS How long it takes for the music to fade in, in MS.
          \return True if success, false on error. */
      bool playMusic(DataObject* music, iReal loops = 0, Real startSeconds = 0, iReal fadeTimeInMS = 500);

      //! Adds a track to play later.
      /*! \param music The track to add.
          \return True if success, false if DataObject is not of type Music. */
      bool addTrack(DataObject* music);

      //! Plays the tracklist.
      void playTracklist();

      //! Skips the current track.
      void skipTrack();

      //! Plays the previous track.
      void previousTrack();

      //! Stops playing music
      /*! \return True if success, false on error. */
      bool stopPlayingMuisc();

      //! Pauses music.
      /*! \return True if success, false on error. */
      bool pauseMusic();

      //! Resumes music.
      /*! \return True if success, false on error. */
      bool resumeMusic();

      //! Change the position of where the audio engine is in the world.
      /*! This enables positional audio.
          \param pos The position of the object where the sound comes from
          \param origin Where the person that hears the object is located. */
      void setPosition(const Vector2<Real>& pos, const Vector2<Real>& origin);

    private:

      //! A callback function that keeps the tracks playing.
      static void runTracklistCallback();

      //! Are we currently playing the tracklist?
      static bool m_playingTracklist;
           //m_playingMusic;

      //! Our vector of tracks.
      static vector<Music*> m_trackList;

      //! Our track that is currently playing.
      static vector<Music*>::const_iterator m_playingTrack;

      //! Do we need to init SDL_mixer?
      static bool m_needToInit;
      iReal m_frequency,
            m_channels,
            m_chunkSize;
      Uint16 m_format;

  };
}
#endif
